package persistence;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;

/**
 * Configures and provides access to Hibernate sessions, tied to the current
 * thread of execution. Follows the Thread Local Session pattern, see
 * {@link http://hibernate.org/42.html}.
 */
public class HibernateUtil {

	/**
	 * Location of hibernate.cfg.xml file. NOTICE: Location should be on the
	 * classpath as Hibernate uses #resourceAsStream style lookup for its
	 * configuration file. That is place the config file in a Java package - the
	 * default location is the default Java package.<br>
	 * <br>
	 * Examples: <br>
	 * <code>CONFIG_FILE_LOCATION = "/hibernate.conf.xml". 
	 * CONFIG_FILE_LOCATION = "/com/foo/bar/myhiberstuff.conf.xml".</code>
	 */
	private static String CONFIG_FILE_LOCATION = "persistence/conf/hibernate.cfg.xml";

	/** Holds a single instance of Session */
	private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

	/** The single instance of hibernate SessionFactory */
	private static org.hibernate.SessionFactory sessionFactory;

	private static Configuration configuration;
	
	//TODO rever hibernate
	static {
		try {
			// Create the SessionFactory from hibernate.cfg.xml
			configuration = new Configuration();
			sessionFactory = configuration.configure(CONFIG_FILE_LOCATION)
					.buildSessionFactory();
		} catch (Throwable ex) {
			// Make sure you log the exception, as it might be swallowed
			System.err.println("Initial SessionFactory creation failed." + ex);
			throw new ExceptionInInitializerError(ex);
		}
	}

	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public static void createDatabase() {
		new SchemaExport(configuration).create(false, true);
	}
	
	public static void dropDatabase() {
		new SchemaExport(configuration).drop(false, true);
	}

	/**
	 * Returns the ThreadLocal Session instance. Lazy initialize the
	 * <code>SessionFactory</code> if needed.
	 * 
	 * @return Session
	 * @throws HibernateException
	 */
	public static Session currentSession() {
		Session session = (Session) threadLocal.get();
		if (session != null && !session.isOpen()) {
			session = null;
		}

		if (session == null) {
			if (sessionFactory == null) {
				try {
					sessionFactory = new AnnotationConfiguration().addPackage(
							"src.model").addAnnotatedClass(
							model.VadeMecumMultimedia.class).configure(
							CONFIG_FILE_LOCATION).buildSessionFactory();
				} catch (Exception e) {
					System.err
							.println("%%%% Error Creating HibernateSessionFactory %%%%");
					e.printStackTrace();
				}
			}
			session = sessionFactory.openSession();
			threadLocal.set(session);
		}
		return session;
	}

	/**
	 * Close the single hibernate session instance.
	 * 
	 * @throws HibernateException
	 */
	public static void closeSession() throws HibernateException {
		Session session = (Session) threadLocal.get();
		threadLocal.set(null);

		if (session != null) {
			session.close();
		}
	}

	/**
	 * Default constructor.
	 */
	private HibernateUtil() {
	}

}
